//
//  AWAckMessage.m
//  AtWork2
//
//  Created by lucas on 15/4/23.
//  Copyright (c) 2015年 Foreveross. All rights reserved.
//

#import "AWAckMessage.h"
#import "ATWUtil.h"

inline AWAckMessageType parseWithAckMessageType(NSString *type) {
    if ([type.uppercaseString isEqualToString:AWMessageKAckRecv]) {
        return AWAckMessageTypeRecv;
    }
    if ([type.uppercaseString isEqualToString:AWMessageKAckRead]) {
        return AWAckMessageTypeRead;
    }
    if ([type.uppercaseString isEqualToString:AWMessageKAckWrite]) {
        return AWAckMessageTypeWrite;
    }
    return NSNotFound;
}

static inline NSString * buildAckMessageTypeWith(AWAckMessageType type) {
    switch (type) {
        case AWAckMessageTypeRecv:
            return AWMessageKAckRecv;
        case AWAckMessageTypeRead:
            return AWMessageKAckRead;
        case AWAckMessageTypeWrite:
            return AWMessageKAckWrite;
    }
}

static inline NSString * buildStringWithArray(NSArray *array) {
    return [array componentsJoinedByString:@","];
}

@interface AWAckMessage ()

@property (nonatomic, strong, readwrite) NSArray *ackIds;

@property (nonatomic, assign, readwrite) AWAckMessageType ackMessageType;

@property (nonatomic, assign, readwrite) UInt64 ackTime;

@end

@implementation AWAckMessage

+ (instancetype)ackMessageOfWriteWithFrom:(NSString *)from to:(NSString *)to ackIds:(NSArray *)ackIds ackTime:(UInt64)ackTime {
    return [[self alloc] initOfWriteWithFrom:(NSString *)from to:(NSString *)to ackIds:ackIds ackTime:ackTime];
}

+ (instancetype)ackMessageOfRecvWithFrom:(NSString *)from to:(NSString *)to ackIds:(NSArray *)ackIds ackTime:(UInt64)ackTime {
    return [[self alloc] initOfRecvWithFrom:(NSString *)from to:(NSString *)to ackIds:ackIds ackTime:ackTime];
}

+ (instancetype)ackMessageOfRecvWithFrom:(NSString *)from to:(NSString *)to ackIds:(NSArray *)ackIds {
    return [[self alloc] initOfRecvWithFrom:(NSString *)from to:(NSString *)to ackIds:ackIds ackTime:[ATWUtil dateOfCurrentTimestamp]];
}

+ (instancetype)ackMessageOfReadWithFrom:(NSString *)from to:(NSString *)to ackIds:(NSArray *)ackIds ackTime:(UInt64)ackTime {
    return [[self alloc] initOfReadWithFrom:(NSString *)from to:(NSString *)to ackIds:ackIds ackTime:ackTime];
}

- (instancetype)initOfWriteWithFrom:(NSString *)from to:(NSString *)to ackIds:(NSArray *)ackIds ackTime:(UInt64)ackTime {
    if (self = [self initWithFrom:(NSString *)from to:(NSString *)to ackTime:ackTime ackMessageType:AWAckMessageTypeWrite]) {
        self.ackIds = ackIds;
    }
    return self;
}

- (instancetype)initOfRecvWithFrom:(NSString *)from to:(NSString *)to ackIds:(NSArray *)ackIds ackTime:(UInt64)ackTime {
    if (self = [self initWithFrom:(NSString *)from to:(NSString *)to ackTime:ackTime ackMessageType:AWAckMessageTypeRecv]) {
        self.ackIds = ackIds;
    }
    return self;
}

- (instancetype)initOfReadWithFrom:(NSString *)from to:(NSString *)to ackIds:(NSArray *)ackIds ackTime:(UInt64)ackTime {
    if (self = [self initWithFrom:(NSString *)from to:(NSString *)to ackTime:ackTime ackMessageType:AWAckMessageTypeRead]) {
        self.ackIds = ackIds;
    }
    return self;
}

- (instancetype)initWithFrom:(NSString *)from to:(NSString *)to ackTime:(UInt64)ackTime
         ackMessageType:(AWAckMessageType)ackMessageType {
    if (self = [super initWithFrom:from to:to messageType:AWMessageTypeAck]) {
        self.ackTime = ackTime;
        self.ackMessageType = ackMessageType;
    }
    return self;
}

#pragma mark Getter Setter Methods

- (void)setAckMessageType:(AWAckMessageType)type {
    [self bodyWithKey:AWMessageKType value:buildAckMessageTypeWith(type)];
}

- (AWAckMessageType)ackMessageType {
   return parseWithAckMessageType([self bodyValueForKey:AWMessageKType]);
}

- (void)setAckIds:(NSArray *)ackIds {
    NSParameterAssert(ackIds);
    [self bodyWithKey:AWMessageKAckIds value:ackIds];
}

- (NSArray *)ackIds {
    return [self bodyValueForKey:AWMessageKAckIds];
}

- (void)setAckTime:(UInt64)ackTime {
    [self bodyWithKey:AWMessageKAckTime value:@(ackTime)];
}

- (UInt64)ackTime {
    return [[self bodyValueForKey:AWMessageKAckTime] unsignedLongLongValue];
}

- (NSString *)sessionIdentifier {
    return [self bodyValueForKey:AWMessageKSessionIdentifier];
}

- (void)setSessionIdentifier:(NSString *)sessionIdentifier {
    [self bodyWithKey:AWMessageKSessionIdentifier value:sessionIdentifier];
}

#pragma mark - Override NSObject Methods

- (NSString *)description {
    return [NSString stringWithFormat:@"%@ <%@: %p %@>",
            [super description],
            self.class,
            self,
            @{ @"ackIds": buildStringWithArray(self.ackIds),
               @"ackTime": @(self.ackTime),
               @"ackMessageType": buildAckMessageTypeWith(self.ackMessageType)}];
}

- (NSString *)debugDescription {
    return [NSString stringWithFormat:@"%@ <%@: %p %@>",
            [super debugDescription],
            self.class,
            self,
            @{ @"ackIds": buildStringWithArray(self.ackIds),
               @"ackTime": @(self.ackTime),
               @"ackMessageType": buildAckMessageTypeWith(self.ackMessageType)}];
}

@end
